/**
 * 字段符号引用
 * User: zhikang.peng
 * Date: 2018/04/27 13:59
 */
package heap

import "gitee.com/thghh/jvmgo/classfile"

type FieldRef struct {
	MemberRef
	field *Field
}

func newFieldRef(cp *ConstantPool, fieldRefInfo *classfile.ConstantFieldrefInfo) *FieldRef {
	ref := &FieldRef{}
	ref.cp = cp
	ref.copyMemberRefInfo(&fieldRefInfo.ConstantMemberrefInfo)
	return ref
}

// 解析字段符号引用解析
func (self *FieldRef) ResolvedField() *Field {
	if self.field == nil {
		self.resolveFieldRef()
	}
	return self.field
}

func (self *FieldRef) resolveFieldRef() {
	d := self.cp.class
	c := self.ResolvedClass()
	field := lookupField(c, self.name, self.descriptor)
	if field == nil {
		panic("java.lang.NoSuchFieldError")
	}
	if !field.isAccessibleTo(d) {
		panic("java.lang.IllegalAccessError")
	}
	self.field = field
}

/**
 * 在C中根据字段名和描述符查找字段,如果找不到，在C的直接接口递归应
 * 用这个查找过程。如果还找不到的话，在C的超类中递归应用这个查找过程。
 * 如果仍然找不到，则查找失败。
 */
func lookupField(c *Class, name string, descriptor string) *Field {
	for _, field := range c.fields {
		if field.name == name && field.descriptor == descriptor {
			return field
		}
	}
	for _, iface := range c.interfaces {
		field := lookupField(iface, name, descriptor)
		if field != nil {
			return field
		}
	}
	if c.superClass != nil {
		return lookupField(c.superClass, name, descriptor)
	}
	return nil
}
